package com.bruce.pattern.creational.singleton;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CountDownLatch;


/**
 * Created by bruce on 2018/11/2 10:40
 */
@Slf4j
public class MainTest {

    @Test
    public void test1() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {
                    latch.countDown();
                    latch.await();
                    LazySingleton instance = LazySingleton.getInstance();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }).start();
        }
        Thread.sleep(3000);
    }


    @Test
    public void test2() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {
                    latch.countDown();
                    latch.await();
                    StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }).start();
        }
        Thread.sleep(3000);
    }


    @Test
    public void test3() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {
                    latch.countDown();
                    latch.await();
                    HungrySingleton instance = HungrySingleton.getInstance();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }).start();
        }
        Thread.sleep(3000);
    }


    @Test
    public void test4() throws IOException, ClassNotFoundException {
        HungrySingleton instance = HungrySingleton.getInstance();
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
        oos.writeObject(instance);

        File file = new File("singleton_file");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));

        HungrySingleton newInstance = (HungrySingleton) ois.readObject();

        System.out.println(instance);
        System.out.println(newInstance);
        System.out.println(instance == newInstance);
    }

    @Test
    public void test5() throws Exception {
        Class objectClass = LazySingleton.class;

        Constructor constructor = objectClass.getDeclaredConstructor();
        constructor.setAccessible(true);
        LazySingleton newInstance = (LazySingleton) constructor.newInstance();
        LazySingleton instance = LazySingleton.getInstance();

        System.out.println(newInstance);
        System.out.println(instance);
    }


    @Test
    public void test6() throws Exception {
        EnumInstance.getInstance().setData("哈哈哈");

        System.out.println(EnumInstance.getInstance().getData());
        System.out.println(EnumInstance.INSTANCE.getData());
        System.out.println(EnumInstance.INSTANCE.hashCode());
        System.out.println(EnumInstance.getInstance().hashCode());
    }

    @Test
    public void test7() throws Exception {
        EnumManySingletonInstance.INSTANCE2.handle();
        EnumManySingletonInstance instance1 = EnumManySingletonInstance.INSTANCE;
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
        oos.writeObject(instance1);
        File file = new File("singleton_file");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        EnumManySingletonInstance newInstance = (EnumManySingletonInstance) ois.readObject();
        System.out.println(instance1.hashCode());
        System.out.println(newInstance.hashCode());
        System.out.println(instance1 == newInstance);
    }

    @Test
    public void test8() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(() -> {
                try {
                    latch.countDown();
                    latch.await();
                    boolean firstString = ContainerSingletion.putInstance("firstString", Thread.currentThread().getName());
                    //只会有一个为true
                    log.info("" + firstString);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        Thread.sleep(3000);
    }

    @Test
    public void test9() throws InterruptedException {
        System.out.println(ThreadLocalInstance.getInstance());
        System.out.println(ThreadLocalInstance.getInstance());
        System.out.println(ThreadLocalInstance.getInstance());
        CountDownLatch latch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    latch.countDown();
                    latch.await();
                    System.out.println(ThreadLocalInstance.getInstance());
                    //只会有一个为true
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        Thread.sleep(3000);
    }


}
